/*
 *  https://github.com/svaarala/duktape/issues/476
 *
 *  When running out of memory, a protected call will catch the error and will
 *  then proceed to unwind the callstack.  The callstack unwind process needs
 *  to copy variable values from value stack to a scope object (for some
 *  activations).  Because the scope object is not preallocated, this process
 *  requires a memory allocation which may fail.  As a result, a protected call
 *  first correctly catches an out-of-memory error but throws a new error when
 *  doing the unwind which then makes the protected call unsafe and may cause
 *  a fatal error.
 *
 *  This testcase demonstrates the issue.  You need a command line 'duk'
 *  executable which has a limited memory pool, e.g. the 'duk-low' example.
 *  Expect string is for the desktop version with no memory limitations,
 *  this testcase is intended to be run manually.
 */

/*===
outer 100
inner 100
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 99
inner 99
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 98
inner 98
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 97
inner 97
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 96
inner 96
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 95
inner 95
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 94
inner 94
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 93
inner 93
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 92
inner 92
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 91
inner 91
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 90
inner 90
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 89
inner 89
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 88
inner 88
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 87
inner 87
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 86
inner 86
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 85
inner 85
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 84
inner 84
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 83
inner 83
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 82
inner 82
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 81
inner 81
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 80
inner 80
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 79
inner 79
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 78
inner 78
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 77
inner 77
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 76
inner 76
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 75
inner 75
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 74
inner 74
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 73
inner 73
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 72
inner 72
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 71
inner 71
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 70
inner 70
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 69
inner 69
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 68
inner 68
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 67
inner 67
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 66
inner 66
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 65
inner 65
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 64
inner 64
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 63
inner 63
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 62
inner 62
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 61
inner 61
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 60
inner 60
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 59
inner 59
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 58
inner 58
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 57
inner 57
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 56
inner 56
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 55
inner 55
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 54
inner 54
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 53
inner 53
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 52
inner 52
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 51
inner 51
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 50
inner 50
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 49
inner 49
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 48
inner 48
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 47
inner 47
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 46
inner 46
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 45
inner 45
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 44
inner 44
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 43
inner 43
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 42
inner 42
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 41
inner 41
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 40
inner 40
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 39
inner 39
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 38
inner 38
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 37
inner 37
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 36
inner 36
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 35
inner 35
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 34
inner 34
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 33
inner 33
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 32
inner 32
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 31
inner 31
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 30
inner 30
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 29
inner 29
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 28
inner 28
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 27
inner 27
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 26
inner 26
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 25
inner 25
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 24
inner 24
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 23
inner 23
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 22
inner 22
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 21
inner 21
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 20
inner 20
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 19
inner 19
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 18
inner 18
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 17
inner 17
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 16
inner 16
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 15
inner 15
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 14
inner 14
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 13
inner 13
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 12
inner 12
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 11
inner 11
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 10
inner 10
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 9
inner 9
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 8
inner 8
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 7
inner 7
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 6
inner 6
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 5
inner 5
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 4
inner 4
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 3
inner 3
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 2
inner 2
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 1
inner 1
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
outer 0
inner 0
1045 1146 1245 1345 1445 1545 1645 1745 1845 1945
finished
===*/

function recursive(n) {
    /* Large register frame and an inner function ensures that when the
     * activation unwinds the lexical scope is copied a lot of variables
     * which requires the scope object's property table to grow (if not
     * pregrown).
     */
    var x00 = 100, x01 = 101, x02 = 102, x03 = 103, x04 = 104, x05 = 105, x06 = 106, x07 = 107, x08 = 108, x09 = 109;
    var x11 = 110, x11 = 111, x12 = 112, x13 = 113, x14 = 114, x15 = 115, x16 = 116, x17 = 117, x18 = 118, x19 = 119;
    var x20 = 120, x21 = 121, x22 = 122, x23 = 123, x24 = 124, x25 = 125, x26 = 126, x27 = 127, x28 = 128, x29 = 129;
    var x30 = 130, x31 = 131, x32 = 132, x33 = 133, x34 = 134, x35 = 135, x36 = 136, x37 = 137, x38 = 138, x39 = 139;
    var x40 = 140, x41 = 141, x42 = 142, x43 = 143, x44 = 144, x45 = 145, x46 = 146, x47 = 147, x48 = 148, x49 = 149;
    var x50 = 150, x51 = 151, x52 = 152, x53 = 153, x54 = 154, x55 = 155, x56 = 156, x57 = 157, x58 = 158, x59 = 159;
    var x60 = 160, x61 = 161, x62 = 162, x63 = 163, x64 = 164, x65 = 165, x66 = 166, x67 = 167, x68 = 168, x69 = 169;
    var x70 = 170, x71 = 171, x72 = 172, x73 = 173, x74 = 174, x75 = 175, x76 = 176, x77 = 177, x78 = 178, x79 = 179;
    var x80 = 180, x81 = 181, x82 = 182, x83 = 183, x84 = 184, x85 = 185, x86 = 186, x87 = 187, x88 = 188, x89 = 189;
    var x90 = 190, x91 = 191, x92 = 192, x93 = 193, x94 = 194, x95 = 195, x96 = 196, x97 = 197, x98 = 198, x99 = 199;

    print('outer', n);

    // Inner function currently causes Duktape to save the outer scope.
    // Reference all the variables so that they will be kept in unwound
    // even if the scope copying is optimized (not in Duktape 1.4.0 yet
    // but planned).
    function inner() {
        print('inner', n);
        print(x00 + x01 + x02 + x03 + x04 + x05 + x06 + x07 + x08 + x09,
              x11 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19,
              x20 + x21 + x22 + x23 + x24 + x25 + x26 + x27 + x28 + x29,
              x30 + x31 + x32 + x33 + x34 + x35 + x36 + x37 + x38 + x39,
              x40 + x41 + x42 + x43 + x44 + x45 + x46 + x47 + x48 + x49,
              x50 + x51 + x52 + x53 + x54 + x55 + x56 + x57 + x58 + x59,
              x60 + x61 + x62 + x63 + x64 + x65 + x66 + x67 + x68 + x69,
              x70 + x71 + x72 + x73 + x74 + x75 + x76 + x77 + x78 + x79,
              x80 + x81 + x82 + x83 + x84 + x85 + x86 + x87 + x88 + x89,
              x90 + x91 + x92 + x93 + x94 + x95 + x96 + x97 + x98 + x99);
    }
    inner();

    // Recurse until out-of-memory (or out of patience).
    if (n > 0) {
        recursive(n - 1);
    } else {
        ;
    }
}

function test() {
    recursive(100);
}

// No try-catch to avoid memory allocations.
test()
print('finished');
